#if UNITY_EDITOR
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;

namespace JH
{
    /// <summary>
    /// Project视口的 文件夹/文件 名称翻译器
    /// </summary>
    public class ProjectNameTranslator : EditorWindow
    {
        /// <summary>
        ///  存储的需要翻译的路径实体
        /// </summary>
        private static PathNeedTranslateEntity _entity;

        private static bool _lastIsPlaying;

        /// <summary>
        ///  序列化设置
        /// </summary>
        private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings()
        {
            //忽略空值
            NullValueHandling = NullValueHandling.Ignore,
            //格式化
            Formatting = Formatting.Indented,
        };

        /// <summary>
        ///  需要翻译的路径的Json存储
        /// </summary>
        private static string PathNeedTranslateJsonPath
        {
            get
            {
                var savePath = Application.dataPath + "/../ProjectSettings/com.jh.common/ProjectNameTranslator.json";
                var folder = Path.GetDirectoryName(savePath);
                if (!string.IsNullOrWhiteSpace(folder) && !Directory.Exists(folder)) Directory.CreateDirectory(folder);
                return savePath;
            }
        }


        [InitializeOnLoadMethod]
        private static void InitProjectNameTranslator()
        {
            // 初始化字典或从已序列化的数据中加载它
            LoadDictionary();

            //资产窗口中的项目
            EditorApplication.projectWindowItemOnGUI += OnProjectWindowGUI;

            //层级窗口
            EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyWindowGUI;

            //初始化上一次是否在运行
            _lastIsPlaying = UnityEditorInternal.InternalEditorUtility.isApplicationActive;

            //监听文件改变
            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = Path.GetDirectoryName(PathNeedTranslateJsonPath);
            watcher.Filter = Path.GetFileName(PathNeedTranslateJsonPath);
            watcher.Changed += (sender, args) =>
            {
                // 重新加载字典
                LoadDictionary();
            };
            watcher.EnableRaisingEvents = true;
        }

        private static void OnEditorUpdate()
        {
            if (_lastIsPlaying != UnityEditorInternal.InternalEditorUtility.isApplicationActive)
            {
                _lastIsPlaying = UnityEditorInternal.InternalEditorUtility.isApplicationActive;
                if (!_lastIsPlaying)
                {
                    //保存字典
                    var json = JsonConvert.SerializeObject(_entity, Settings);
                    File.WriteAllText(PathNeedTranslateJsonPath, json);
                }
            }
        }

        private static void LoadDictionary()
        {
            if (File.Exists(PathNeedTranslateJsonPath))
            {
                var json = File.ReadAllText(PathNeedTranslateJsonPath);
                _entity = JsonConvert.DeserializeObject<PathNeedTranslateEntity>(json);
            }
            else
            {
                _entity = new PathNeedTranslateEntity();
            }
        }

        [MenuItem("Tools/JH/翻译/打开翻译json文件 #&t")]
        private static void OpenTranslateJson()
        {
            if (File.Exists(PathNeedTranslateJsonPath)) Process.Start("notepad.exe", PathNeedTranslateJsonPath);
        }

        [MenuItem("Tools/JH/翻译/清空翻译存储")]
        private static void ClearTranslate()
        {
            _entity.LabelToTranslateResult.Clear();
            File.Delete(PathNeedTranslateJsonPath);
        }

        /// <summary>
        /// 添加一个菜单项到Assets右键菜单中，并设置执行函数
        /// </summary>
        [MenuItem("Assets/Translate")]
        private static async void TranslateAsset()
        {
            // 获取当前选定的对象
            Object[] selectedObjects = Selection.GetFiltered(typeof(Object), SelectionMode.Assets);

            // 遍历选定的对象
            foreach (Object selectedObject in selectedObjects)
            {
                string assetPath = AssetDatabase.GetAssetPath(selectedObject);
                if (assetPath == null) continue;

                var label = GetLabelFromPath(assetPath);

                //如果存在则移除
                if (_entity.LabelToTranslateResult.Keys.Contains(label))
                {
                    RemoveLabelFromDict(label);
                }
                else
                {
                    await AddLabelToDict(label);
                }
            }

            //保存字典
            var json = JsonConvert.SerializeObject(_entity, Settings);
            await File.WriteAllTextAsync(PathNeedTranslateJsonPath, json);
        }

        [MenuItem("GameObject/Translate")]
        private static async void TranslateGo()
        {
            // 获取当前选定的对象
            Object[] selectedObjects = Selection.GetFiltered(typeof(GameObject), SelectionMode.Editable);
            // 遍历选定的对象
            foreach (Object selectedObject in selectedObjects)
            {
                if (selectedObject is not GameObject go) continue;
                string label = SplitCamelCase(go.name);

                //如果存在则移除
                if (_entity.LabelToTranslateResult.Keys.Contains(label))
                {
                    RemoveLabelFromDict(label);
                }
                else
                {
                    await AddLabelToDict(label);
                }
            }

            //保存字典
            var json = JsonConvert.SerializeObject(_entity, Settings);
            await File.WriteAllTextAsync(PathNeedTranslateJsonPath, json);
        }

        /// <summary>
        ///  将一个标签从需要翻译的字典中移除
        /// </summary>
        private static void RemoveLabelFromDict(string label)
        {
            _entity.LabelToTranslateResult.Remove(label);
        }

        /// <summary>
        ///  将一个标签添加到需要翻译的字典中
        /// </summary>
        private static async JTask AddLabelToDict(string label)
        {
            await TextTranslationHelper.TranslateToCn(label,
                result => { _entity.LabelToTranslateResult.TryAdd(label, result); });
        }

        /// <summary>
        ///  项目窗口
        /// </summary>
        private static void OnProjectWindowGUI(string guid, Rect selectionRect)
        {
            // 获取当前项目窗口中的对象路径
            string path = AssetDatabase.GUIDToAssetPath(guid);
            if (string.IsNullOrEmpty(path)) return;

            //当前选中的对象
            Object selectedObject = Selection.activeObject;

            //当前选中对象的guid
            string selectedGuid = selectedObject != null
                ? AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(selectedObject))
                : null;

            //判断当前绘制对象是否是选中对象
            bool isSelected = selectedObject != null && selectedGuid == guid;

            // 获取标签值
            string labelValue = GetTranslateValue(GetLabelFromPath(path));

            // 绘制标签值
            DrawLabelValue(labelValue, selectionRect, isSelected);
        }

        /// <summary>
        ///  层级窗口
        /// </summary>
        private static void OnHierarchyWindowGUI(int instanceID, Rect selectionRect)
        {
            //当前选中的对象
            Object selectedObject = Selection.activeObject;

            //当前选中对象是否是当前绘制对象
            bool isSelected = selectedObject != null && selectedObject.GetInstanceID() == instanceID;

            //获取当前对象
            var currentDraw = EditorUtility.InstanceIDToObject(instanceID);

            // 获取当前标签值
            string label = currentDraw != null ? SplitCamelCase(currentDraw.name) : null;

            // 获取标签值
            string labelValue = GetTranslateValue(label);

            // 绘制标签值
            DrawLabelValue(labelValue, selectionRect, isSelected);
        }

        /// <summary>
        ///  绘制标签值
        /// </summary>
        private static void DrawLabelValue(string labelValue, Rect selectionRect, bool isSelected)
        {
            // 如果没标签有值，返回
            if (string.IsNullOrEmpty(labelValue)) return;

            //ICON的宽度
            float iconWidth = 16f;

            // 创建一个GUIStyle对象，您可以自定义这个样式以匹配您的UI
            GUIStyle labelStyle = new GUIStyle(EditorStyles.label)
            {
                alignment = TextAnchor.MiddleLeft, // 确保文本是从左边开始绘制的
                normal = { textColor = Color.yellow }, // 设置标签的颜色
                clipping = TextClipping.Clip // 设置文本超出边界时的处理方式
            };

            // 创建一个GUIContent对象，包含您要测量的字符串
            GUIContent labelContent = new GUIContent(labelValue);

            // 计算字符串的尺寸
            Vector2 labelSize = labelStyle.CalcSize(labelContent);

            // 设置新的标签位置和大小
            // selectionRect.x 是左边的起始位置
            // 调整Rect的宽度和x位置，以便为图标留出空间
            Rect rect = new Rect(selectionRect.x + iconWidth, selectionRect.y,
                selectionRect.width, selectionRect.height);

            // 绘制一个背景矩形来覆盖原有的文本（根据需要进行颜色调整）
            EditorGUI.DrawRect(rect,
                isSelected
                    ? new Color(0.1803922f, 0.3529412f, 0.4980392f)
                    : new Color(0.2196079f, 0.2196079f, 0.2196079f)); // 使用与编辑器接近的背景色

            // 现在您可以使用rect来绘制您的标签，它将覆盖原来的文本
            GUI.Label(rect, labelValue, labelStyle);
        }

        /// <summary>
        /// 获取标签翻译的存储值
        /// </summary>
        private static string GetTranslateValue(string name)
        {
            if (string.IsNullOrWhiteSpace(name)) return null;

            return _entity.LabelToTranslateResult.GetValueOrDefault(name);
        }

        private static string GetLabelFromPath(string path)
        {
            // 检查路径是否存在
            if (!File.Exists(path) && !Directory.Exists(path))
            {
                // 路径不存在
                return null;
            }

            // 检查路径是文件还是文件夹
            FileAttributes attr = File.GetAttributes(path);
            var ret = (attr & FileAttributes.Directory) == FileAttributes.Directory
                ? new DirectoryInfo(path).Name // 路径是一个文件夹,返回文件夹名称
                : Path.GetFileNameWithoutExtension(path); // 路径是一个文件  返回不带扩展名的文件名

            return SplitCamelCase(ret);
        }

        /// <summary>
        /// 将驼峰命名转换为带空格的命名
        /// </summary>
        private static string SplitCamelCase(string input)
        {
            // 这个正则表达式会在非开头的大写字母前面添加空格
            return Regex.Replace(input, @"(?<!^)([A-Z])", " $1").Trim();
        }
    }
}
#endif